﻿<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Анимация вдоль пути</title>
<link rel="stylesheet" type="text/css" href="../lib/styles.css"/>
<script type="text/javascript" src="../lib/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="../lib/raphael-min.js"></script>
<script type="text/javascript">
	$(function(){
		var paper = new Raphael($("#paper1")[0]);
		var duration = 5000;
		
		Raphael.fn.rosetta = function(x,y,rx,ry,N) {
			if (N == 0) {
				console.log("no diving by zero, please"); return;
			}
			var angle = 360 / N; // negative values of N are fine
			var path = "M" + x + "," + y;
			
			for (var c = 0; c < N; c += 1) {
				// need angle for each leaf of rosetta in radians
				var theta = angle * c * Math.PI / 180;
				// coords of farthest point from center for this leaf
				var dx = x + 2 * rx * Math.cos(theta),
					dy = y + 2 * rx * Math.sin(theta);
				path += "A" + rx + "," + ry + " " + angle*c + " 1,1 " + dx + "," + dy;
				path += "A" + rx + "," + ry + " " + angle * c + " 1,1 " + x + "," + y;
			}
			return paper.path(path);        
		}

		paper.customAttributes.progress = function (v) {
			var path = this.data("mypath"),
				attrs = this.attr(),
				offset = { x: 0, y: 0 };

			if (!path) return{transform: "t0,0"};
			
			if (attrs.hasOwnProperty("width")) {
				offset.x = -this.attr("width") / 2;
				offset.y = -this.attr("height") / 2;
			}
			
			var len = path.getTotalLength();
			var point = path.getPointAtLength(v * len);

			var trail = this.data("mytrail");
			if (trail) {
				trail.attr("path", path.getSubpath(0, v * len));
			}
			
			return {
				transform: "t" + (point.x + offset.x) + "," + (point.y + offset.y) + 
				"r" + (point.alpha < 180 ? point.alpha + 180 : point.alpha)
			};
		};

		var rose = paper.rosetta(120, 120, 55, 35, 6).attr("stroke", "#ccc");
		var trail = paper.path("M0,0").attr({stroke: "red", 'stroke-width': 3});
		var shape = paper.rect(0, 0, 20, 10).attr("fill", "green");

		shape.data("mypath", rose);
		shape.data("mytrail", trail);
		shape.attr("progress", 0);
		shape.animate({ progress: 1 }, duration);
		
	});
</script>
</head>
<body>
	<h1>Анимация вдоль пути</h1>
	<p>Источник: [1], стр. 87 "Animating Along a Path"</p>
	<p>Указания: прямоугольник движется вдоль сложного пути, оставляя за собой след</p>
	<p>Особенности:</p>
	<ul>
		<li>к атрибутам объектов добавлен новый атрибут <span class="code">progress</span>, устанавливающий параметры преобразования фигуры в зависимости от степени завершенности анимации</li>
		<li>анимация описана как процесс изменения нового атрибута <span class="code">progress</span></li>
		<li>для определения текущих координат объекта используется функция <span class="code">getPointAtLength()</span></li>
		<li>ориентация объекта вдоль траектории осуществляется засчет свойства <span class="code">alpha</span> точки, получаемой при вызове функции <span class="code">getPointAtLength()</span> (точка указывает положение касательной к кривой в данной точке)</li>
	</ul>
	
	<p class="attention">В [1] отмечается, что такой эффект удобен для анимации "рукописных" надписей.</p>

	<div id="paper1" class="paper" style="width:600px; height:400px;">
	</div>
	
	<h2>Литература</h2>
	<ol>
		<li>Wilson, C. RaphaelJS Graphics and Visualization on the Web. O'Relly, 2013 г.</li>
	</ol>
</body>
</hmtl>